home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 076-100 / scopedisk83 / popcli4 / popparse.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  10KB  |  351 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  6. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9. /*
  10.  * VERY loosely based on the input.device example by Rob Peck, 12/1/85
  11.  */
  12.  
  13. #include "popcli.h"
  14. #include "popbug.h"
  15.  
  16. /* KLUDGE: (sort of) These strings can ONLY be accessed if gptr->stdout */
  17. /*         is non-zero, since they *should* be in the PopCLI hunk that  */
  18. /*         gets thrown away.                                            */
  19. #define CSI "\x9B"
  20. #define HILIT CSI "0;33m"
  21. #define BOLD  CSI "1m"
  22. #define PLAIN CSI "0m"
  23. #define COPYR "\xA9"
  24.  
  25. char    killmsg[] =
  26.    HILIT "PopCLI IV" PLAIN " Terminating\n";
  27.  
  28. char    banner[] =
  29.    HILIT "PopCLI IV" PLAIN
  30.    " - Copyright " COPYR " 1987,1989 The Software Distillery\n"
  31.    " 235 Trillingham Lane, Cary NC 27513   BBS:(919)-471-6436\n";
  32.  
  33. char    helpmsg[] =
  34.    "Usage:\n"
  35.    "  " BOLD "POPCLI" PLAIN " [[secs | ADD | REPL] [key]] [[cmdmods] [CMD] cmnd]\n"
  36.    "  " BOLD "POPCLI" PLAIN " FREE [key]\n"
  37.    "  " BOLD "POPCLI" PLAIN " EXEC [key]\n"
  38.    "  " BOLD "POPCLI" PLAIN " BLANK\n"
  39.    "  " BOLD "POPCLI" PLAIN " UNBLANK\n"
  40.    "  " BOLD "POPCLI" PLAIN " TIME n\n"
  41.    "  " BOLD "POPCLI" PLAIN " QUIT\n"
  42.    "  cmdmods: [NOWB] [MINMEM n] [MINCHIP n]\n"
  43.    "where:\n"
  44.    " secs    is the number of seconds before blanking screen\n"
  45.    " key     is the scan code for the key to press with Left Amiga\n"
  46.    "         <decimal>, 0x<hex>, F{1-10}, DEL, ESC, or 'c',\n"
  47.    "         where c is any ASCII character from ' ' to '~'\n"
  48.    " ADD     Activates Left Amiga-<key> without altering the blanking time\n"
  49.    " REPL    Same as ADD, but more mnemonic for redefining a key\n"
  50.    " NOWB    don't bring the workbench screen to front before executing command\n"
  51.    " MINMEM  Make sure at least n bytes are available before executing command\n"
  52.    " MINCHIP Like MINMEM, but checks for chip memory only.\n"
  53.    " CMD     Optional tag, in case command starts with a keyword or number\n"
  54.    " cmnd    is to be executed when Left Amiga-<key> is pressed\n"
  55.    " FREE    Deactivates Left Amiga-<key>, but leaves POPCLI up\n"
  56.    " EXEC    Executes the given key\n"
  57.    " BLANK   Blanks the screen immediately\n"
  58.    " UNBLANK Unblanks the screen, resetting the timer countdown\n"
  59.    " TIME    Sets the timeout value without clobbering any key definitions\n"
  60.    " QUIT    Brings down POPCLI and all command keys.\n"
  61.    "\n"
  62.    "From ARexx: ADDRESS POPCLI4 <popcli-arguments>\n";
  63.  
  64. /* Make this a multiple of 2 bytes long!!! */
  65. struct KEYWORD {
  66.     char    name[8];
  67.     char    command;
  68.     char    wherenum;
  69. };
  70.  
  71. #define KW_QUIT 0
  72. #define KW_NOWB    1
  73. #define KW_CMD    2
  74. #define KW_ESC  3
  75. #define KW_DEL  4
  76. #define KW_ADD    5
  77. #define KW_REPL 6
  78. #define KW_FREE    7
  79. #define KW_TIME    8
  80. #define KW_MEM    9
  81. #define KW_CHIP    10
  82. #define KW_EXEC 11
  83. #define KW_BLNK 12
  84. #define KW_UNBL 13
  85.  
  86. #define NUM_NONE 0
  87. #define NUM_KEY    1
  88. #define NUM_TIME 2
  89. #define NUM_MEM -1
  90. #define NUM_CHIP -2
  91.  
  92. #define ISMEMNUM(n)    (n < 0)
  93.  
  94. #ifdef CONST_KLUDGE
  95. #define    PARSETBL_KLUDGE                    \
  96.     "quit\0\0\0\0"    "\04"        "\01"        \
  97.     "nowb\0\0\0\0"    "\00"        "\01"        \
  98.     "cmd\0\0\0\0\0"    "\00"        "\01"        \
  99.     "esc\0\0\0\0\0"    "\00"        "\01"        \
  100.     "del\0\0\0\0\0"    "\00"        "\01"        \
  101.     "add\0\0\0\0\0"    "\01"        "\01"        \
  102.     "repl\0\0\0\0"    "\01"        "\01"        \
  103.     "free\0\0\0\0"    "\02"        "\01"        \
  104.     "time\0\0\0\0"    "\07"        "\02"        \
  105.     "minmem\0\0"    "\00"        "\xff"        \
  106.     "minchip\0"    "\00"        "\xfe"        \
  107.     "exec\0\0\0\0"    "\03"        "\01"        \
  108.     "blank\0\0\0"    "\05"        "\01"        \
  109.     "unblank\0"    "\06"        "\01"        \
  110.         "\00"   /* To ensure even alignment */
  111.  
  112. #define KW_MAX 14
  113.  
  114.  
  115. #else
  116. const struct KEYWORD parsetbl[] = {
  117.     { "quit",    MSG_SHUTDOWN,    NUM_KEY  },
  118.     { "nowb",    MSG_NONE,    NUM_KEY  },
  119.     { "cmd",    MSG_NONE,    NUM_KEY  },
  120.     { "esc",    MSG_NONE,    NUM_KEY  },
  121.     { "del",    MSG_NONE,    NUM_KEY  },
  122.     { "add",    MSG_ADDKEY,    NUM_KEY  },
  123.     { "repl",    MSG_ADDKEY,    NUM_KEY  },
  124.     { "free",    MSG_DELKEY,    NUM_KEY  },
  125.     { "time",    MSG_SETTIME,    NUM_TIME },
  126.     { "minmem",    MSG_NONE,    NUM_MEM  },
  127.     { "minchip",    MSG_NONE,    NUM_CHIP },
  128.     { "exec",    MSG_EXECUTE,    NUM_KEY  },
  129.     { "blank",    MSG_BLANK,    NUM_KEY  },
  130.     { "unblank",    MSG_UNBLANK,    NUM_KEY  }
  131. };
  132. #define KW_MAX ((sizeof(parsetbl))/(sizeof(struct KEYWORD)))
  133. #endif
  134.  
  135. #define MAXKWLEN 8
  136.  
  137. #define KWCMP(a,b)    ((*(long *)a)   == (*(long *)b) && \
  138.              ((long *)a)[1] == ((long *)b)[1])
  139.  
  140. /* SCODE table characters are in the following order: */
  141.  
  142. /*     !"#$%&'()*+,-./          */
  143. /*      @ABCDEFGHIJKLMNO          */
  144. /*      PQRSTUVWXYZ[\]^_          */
  145. /*      `abcdefghijklmno          */
  146. /*      pqrstuvwxyz{|}~           */
  147.  
  148. #define SCODE                   \
  149.     "\x40\x01\x2a\x03\x04\x05\x07\x2a\x09\x0a\x08\x0c\x38\x0b\x39\x3a"   \
  150.     "\x0a\x01\x02\x03\x04\x05\x06\x07\x08\x09\x29\x29\x38\x0b\x39\x3a"   \
  151.     "\x02\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18"   \
  152.     "\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x06\x0a"   \
  153.     "\x00\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18"   \
  154.     "\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x00\x46"
  155.  
  156. static void WriteOut(  GLOBAL_DATA *, char *, int );
  157.  
  158. void popbanner( gptr )
  159. GLOBAL_DATA    *gptr;
  160. {
  161.     WriteOut( gptr, banner, sizeof(banner)-1 );
  162. }
  163.  
  164. void poptrailer( gptr )
  165. GLOBAL_DATA    *gptr;
  166. {
  167.     WriteOut( gptr, killmsg, sizeof(killmsg)-1 );
  168. }
  169.  
  170. int popparse( gptr, cmd, msg )
  171. GLOBAL_DATA                   *gptr;
  172. register char                 *cmd;
  173. register struct OURMSG        *msg;
  174. {
  175.    long    buff[MAXKWLEN/sizeof(long)+1];
  176.    char *p, *q;
  177.    int  kw;
  178.    int  len;
  179.    int  value;
  180.    char wherenum;
  181. #ifdef CONST_KLUDGE
  182.    struct KEYWORD *parsetbl = (struct KEYWORD *)PARSETBL_KLUDGE;
  183. #endif
  184.  
  185.    msg->type = MSG_ADDKEY;
  186.    msg->interval = 0;
  187.    msg->key = DEFKEY;
  188.    msg->minmem = 0;
  189.    msg->minchip = 0;
  190.    strcpy( msg->command, DEFCMD );
  191.    msg->cmdflags = 0;
  192.  
  193.    wherenum = NUM_TIME;
  194.  
  195.    /* if we were run from CLI then output our banner and process parameters */
  196.    if (!cmd)
  197.       return( OK );
  198.  
  199.    if (*cmd == '?')
  200.    {
  201.       WriteOut(gptr, helpmsg, sizeof(helpmsg)-1);
  202.  
  203.       return( LEAVE );
  204.    }
  205.  
  206.    while( *cmd )
  207.    {
  208.       while (*cmd && *cmd <= ' ') cmd++;
  209.  
  210.       /* Fetch the next keyword into a temp. buffer, lowercasing */
  211.       buff[0] = buff[1] = 0;
  212.  
  213.       for (p = cmd, q = (char *)buff; *p > ' '; *q++ = (*p++ | ' '))
  214.       {
  215.          /* Too long to be a keyword... */
  216.          if (q >= ((char *)buff)+MAXKWLEN)
  217.             goto gotacmd;
  218.       }
  219.  
  220.       for (kw = 0; kw < KW_MAX; kw++)
  221.       {
  222.          if (KWCMP(parsetbl[kw].name, buff))
  223.          {
  224.             /* We found a valid keyword! */
  225.  
  226.             wherenum = parsetbl[kw].wherenum;
  227.             if (parsetbl[kw].command != MSG_NONE)
  228.                msg->type = parsetbl[kw].command;
  229.  
  230.             switch( kw ) {
  231.                case KW_QUIT:
  232.                   return(SHUTDOWN);
  233.                   break;
  234.  
  235.                case KW_NOWB:
  236.                   msg->cmdflags |= FLAG_NOWB2F;
  237.                   break;
  238.  
  239.                case KW_CMD:
  240.                   /* Skip intervening blanks, then treat as a command */
  241.                   for (cmd = p; *cmd && *cmd == ' '; cmd++);
  242.  
  243.                   goto gotacmd;
  244.                   break;
  245.  
  246.                case KW_ESC:
  247.                   msg->key = 0x45;
  248.                   break;
  249.  
  250.                case KW_DEL:
  251.                   msg->key = 0x46;
  252.                   break;
  253.  
  254.                /* These are all handled by the table code!! */
  255.                /* NOTE: I have arranged the parse table such that all */
  256.                /* of these have larger values than the keywords which */
  257.                /* actually *do* something here. I have to comment out */
  258.                /* the case labels, though, because the compiler would */
  259.                /* put them in the jump table anyway. */
  260.             /* case KW_ADD:  */
  261.             /* case KW_REPL: */
  262.             /* case KW_FREE: */
  263.             /* case KW_TIME: */
  264.             /* case KW_MEM:  */
  265.             /* case KW_CHIP: */
  266.             /* case KW_EXEC: */
  267.             /* case KW_BLNK: */
  268.             /* case KW_UNBL: */
  269.                default:
  270.                   break;
  271.             }
  272.  
  273.             goto kwdone;
  274.          }
  275.       }
  276.  
  277.       /* No keywords found; must be a key, number, or command */
  278.  
  279.       if (*((char *)buff) == 'f')
  280.       {
  281.          /* User possibly typed F1-F10, but if not, we don't */
  282.          /* want to complain, just get the command           */
  283.          len = stcd_i( ((char *)buff)+1, &value ) + 1;
  284.  
  285.          if (((char *)buff)[len] || (value < 1) || (value > 10))
  286.             /* Treat it as a command */
  287.             goto gotacmd;
  288.          else
  289.          {
  290.             wherenum = NUM_KEY;
  291.             value += 0x4f; /* Translate to scan code */
  292.          }
  293.       }
  294.       else if (*((short *)buff) == 0x3078)   /* "0x" */
  295.       {
  296.          /* Number is in hex, rather than decimal */
  297.          len = stch_i( ((char *)buff)+2, &value ) + 2;
  298.       }
  299.       else if (*((char *)buff) == '\'')  /* ' */
  300.       {
  301.          /* Number is an actual key picture */
  302.          value = SCODE[(((char *)buff)[1] & 0x7f)-' '];
  303.          len = 3;
  304.       }
  305.       else
  306.          len = stcd_i( (char *)buff, &value );
  307.  
  308.       /* Make sure we got a valid value. If not, must be a */
  309.       /* start of a command.                               */
  310.       if (((char *)buff)[len])
  311.       {
  312.          goto gotacmd;  /* Leaves the function */
  313.       }
  314.  
  315.       if (value && ISMEMNUM(wherenum))
  316.       {
  317.          value = ((value >> 10) + 1);
  318.          if (wherenum == NUM_MEM)
  319.             msg->minmem = value;
  320.          else
  321.             msg->minchip = value;
  322.       }
  323.       else if (wherenum == NUM_TIME)
  324.          msg->interval = value;
  325.       else
  326.          msg->key = value;
  327.  
  328. kwdone:
  329.       cmd = p;
  330.    }
  331.  
  332. gotacmd:
  333.    if (*cmd)
  334.    {
  335.       strncpy( msg->command, cmd, MAXCMD-1 );
  336.       msg->command[MAXCMD-1] = '\0';
  337.    }
  338.  
  339.    return(OK);
  340. }
  341.  
  342. static void WriteOut( gptr, msg, len )
  343. GLOBAL_DATA    *gptr;
  344. char        *msg;
  345. int        len;
  346. {
  347.     if (gptr->stdout)
  348.         Write( gptr->stdout, msg, len );
  349. }
  350.  
  351.